import { Config } from './Config';
import { Col } from "./Col";
import { Tooler } from "./tooler"
import { Core } from './Core';
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import { Coin } from './Coin';
import { Effect } from './Effect';
import { Cube } from './Cube';
import { Card } from './Card';
import { Cache } from './Cache';
import { TimeoutManager } from './TimeoutManager';
import AnimeManager from './AnimeManager';

export class Game {
  cols: Col[] = [];
  core: Core = new Core();
  scene: THREE.Scene = null as any;
  camera: THREE.PerspectiveCamera = null as any;
  timers: number = 0;
  effects: Effect[] = [];
  running = false

  constructor() {

  }

  async init(canvas: HTMLCanvasElement, w: number, h: number): Promise<void> {
    Config.init(w, h);
    Cache.init()

    await Coin.load()
    await Card.load()

    for (let i = 0; i < Config.CARDS_PER_ROW; i++) {
      const col = new Col(i);
      col.init();
      this.cols.push(col);
    }

    this.setup(canvas);

    Config.bus.on("start", (p: any) => {
      const effect = this.effects.length ? this.effects.pop()! : new Effect()
      effect.play();
      effect.position.copy(p)
      this.scene?.add(effect);

      TimeoutManager.setTimeout(() => {
        this.effects.push(effect);
        this.scene?.remove(effect);
      }, Config.CHOOSE_TIMER);
    })

    // 鼠标事件处理
    canvas.addEventListener('click', (event: MouseEvent) => {
      // 获取 canvas 的位置和尺寸
      const rect = canvas.getBoundingClientRect();

      // 将鼠标点击位置转换为 canvas 内的坐标
      const mouse = new THREE.Vector2();
      mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

      // 创建光线投射器
      const raycaster = new THREE.Raycaster();
      raycaster.setFromCamera(mouse, this.camera);

      // 检测与场景中的物体相交
      const intersects = raycaster.intersectObjects(this.scene!.children, true);

      if (intersects.length > 0) {
        console.log(intersects[0].object);
      }
    }, false);

    // 在您的主代码中
    document.addEventListener("visibilitychange", () => {
      if (document.hidden) {
        console.log("暂停")
        TimeoutManager.pauseAll();
        AnimeManager.pauseAll();
      } else {
        console.log("恢复")
        TimeoutManager.resumeAll();
        AnimeManager.resumeAll();
      }
    });

    setInterval(() => {
      AnimeManager.cleanUp();
    }, 60000); // 每分钟清理一次
  }

  private addLights(): void {
    // 环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.64);
    this.scene.add(ambientLight);

    // 主平行光
    const mainLight = new THREE.DirectionalLight(0xffffff, 0.5);
    mainLight.position.set(30, 40, 10);
    this.scene.add(mainLight);

    // 补光
    const fillLight = new THREE.DirectionalLight(0x9090aa, 0.25);
    fillLight.position.set(-100, 50, 80);
    this.scene.add(fillLight);

    // 背光
    // const backLight = new THREE.DirectionalLight(0x9090aa, 0.72);
    // backLight.position.set(0, -100, 90);
    // this.scene.add(backLight);

    // 点光源
    // const pointLight = new THREE.PointLight(0xff8800, 1, 100);
    // pointLight.position.set(0, 100, 30);
    // this.scene.add(pointLight);
  }

  async setup(canvas: HTMLCanvasElement): Promise<void> {

    const w = Config.GAME_WIDTH
    const h = Config.GAME_HEIGHT

    // 创建场景
    const scene = new THREE.Scene();
    this.scene = scene

    // scene.add(new THREE.AxesHelper(400))

    // 创建相机
    const camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 8000);
    this.camera = camera

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer({ canvas });
    renderer.setSize(w, h);

    this.addLights()

    // 添加环境光
    // const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    // scene.add(ambientLight);

    // // 添加平行光
    // const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
    // directionalLight.position.set(1, 1, 1);
    // scene.add(directionalLight);

    this.cols.forEach((col, ci) => {
      col.cubes.forEach((cube, ri) => {
        const position = new THREE.Vector3(
          ci * Config.CARD_WIDTH - Config.GAME_WIDTH / 2 + Config.CARD_WIDTH / 2,
          -ri * Config.CARD_HEIGHT + Config.GAME_HEIGHT / 2 - Config.CARD_HEIGHT / 2,
          0
        );
        if (ri == 0) {
          Config.TOP_Y = position.y;
        }
        if (ri == col.cubes.length - 1) {
          Config.BOTTOM_Y = position.y;
        }
        cube.setPosition(position)
        cube.addToScene(scene)
      })
      col.updateOrder()
    })
    // console.log("config", Config.TOP_Y, Config.BOTTOM_Y)

    // 计算场景的边界框
    const box = new THREE.Box3().setFromObject(scene);
    const size = box.getSize(new THREE.Vector3());
    const center = box.getCenter(new THREE.Vector3());

    // 计算合适的相机位置
    const fov = camera.fov * (Math.PI / 180);
    const cameraZ = Math.abs(Math.max(size.x, size.y) / (2 * Math.tan(fov / 2)));
    camera.position.z = cameraZ * 0.98; // 稍微往后移动一点，以确保所有内容都在视野内

    // 将相机对准场景中心
    camera.lookAt(center);

    // 添加 OrbitControls
    // const controls = new OrbitControls(camera, renderer.domElement);
    // controls.enableDamping = true; // 添加阻尼效果
    // controls.dampingFactor = 0.25;
    // controls.screenSpacePanning = false;

    // 渲染场景
    function animate() {
      requestAnimationFrame(animate);
      // controls.update();
      renderer.render(scene, camera);
    }

    animate();
  }

  async play(): Promise<void> {
    if (this.running) return;
    Config.sounds.playRoll()
    this.running = true
    Config.bus.emit("running", this.running)
    this.timers++;
    const list = await this.core.play();
    list.forEach((items, ci) => {
      const temp = this.cols[ci].add(items);
      temp.forEach((cube, ri) => {
        const position = new THREE.Vector3(
          ci * Config.CARD_WIDTH - Config.GAME_WIDTH / 2 + Config.CARD_WIDTH / 2,
          (temp.length - ri) * Config.CARD_HEIGHT + Config.GAME_HEIGHT / 2 - Config.CARD_HEIGHT / 2,
          0
        );
        cube.setPosition(position)
        cube.addToScene(this.scene!)
      })
    })
    this.core.setCols(this.cols);
    // if(this.timers == 1){
    await this.core.dropDown(true);
    // }
    // this.cols.forEach(col => col.play())
    console.log(this.cols, this.core);
    this.running = false;
    Config.bus.emit("running", this.running)
  }
}